home *** CD-ROM | disk | FTP | other *** search
/ APDL Eductation Resources / APDL Eductation Resources.iso / programs / graphics / gif2rpc / source / 16bpp_48bi / c / dither2x2 < prev    next >
Encoding:
Text File  |  1995-10-16  |  5.0 KB  |  156 lines

  1. /* dither2x2.c
  2.  * AUTHOR:      Cy Booker, cy@cheepnis.demon.co.uk
  3.  * LICENSE:     FreeWare, Copyright (c) 1995 Cy Booker
  4.  */
  5.  
  6. #include "internal.h"
  7.  
  8. #include <assert.h>
  9. #include <string.h>             /* memset() */
  10.  
  11. #include "OS:macros.h"
  12. #include "OS:hourglass.h"
  13.  
  14.  
  15.  
  16. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  17.  */
  18.  
  19. static void calculate_dither2x2(
  20.                 int             dither[2][2],
  21.                 os_colour       colour,
  22.                 rgbtupleout_fn  fn);
  23.                 
  24.  
  25.  
  26. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  27.  */
  28.  
  29. extern bool process_gif_16bpp_dither2x2_48bit(
  30.                 const process_gif       *p) {
  31.   byte                  *rove;
  32.   bits                  dest;
  33.   int                   width, height;
  34.   int                   x, y;
  35.   const os_colour       *palette;
  36.   int                   line_length;
  37.   int                   index;
  38.   int                   dither[256][2][2];
  39.  
  40.   assert(p);
  41.   assert(p->pixel_width > 0);
  42.   assert(p->pixel_height > 0);
  43.   assert(p->in_palette.colours);
  44.   assert(p->fn);
  45.  
  46.   /*
  47.    * pre-calculate dither table
  48.    * to save a function call in middle loop
  49.    * thus the compiler has more registers to play with
  50.    */
  51.   palette = p->in_palette.colours;
  52.   for (index= p->in_palette.ncolours; (index > 0);) {
  53.     index--;
  54.     calculate_dither2x2(dither[index], palette[index], p->fn);
  55.   }
  56.  
  57.   /*
  58.    * not we pre-load values from the process_gif array
  59.    * because it considerably helps the compiler produce better code
  60.    */
  61.   rove = p->buffer;
  62.   width = (p->pixel_width + 1) & ~1;
  63.   height = p->pixel_height;
  64.   line_length = p->line_length;
  65.  
  66.   for (y= height; (y > 0); y--) {
  67.     if ((y & 7) == 0) {
  68.       xhourglass_percentage((y * 100) / height);
  69.     }
  70.     for (x= width - 1; (x >= 0); x--) {
  71.       assert((x & 1) == 1);
  72.       /*
  73.        * writing one 32-bit word is much faster than two 16-bit shorts
  74.        */
  75.       index = rove[x];
  76.       dest = dither[index][y & 1][1];
  77.       x--;
  78.       index = rove[x];
  79.       dest <<= 16;
  80.       dest |= dither[index][y & 1][0];
  81.       *(((int *)rove) + (((unsigned int)x) >> 1)) = dest;
  82.     }
  83.     rove += line_length;
  84.   }
  85.   return FALSE;
  86. }
  87.  
  88.  
  89.  
  90. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  91.  */
  92.  
  93. static void calculate_dither2x2(
  94.                 int             dither[2][2],
  95.                 os_colour       colour,
  96.                 rgbtupleout_fn  fn) {
  97.   int           target_red, target_grn, target_blu;
  98.   int           red, grn, blu;
  99.   rgbtupleout   err;
  100.   register int  err_red, err_grn, err_blu;
  101.   int           t;
  102.  
  103.   assert(dither);
  104.   assert(fn);
  105.   /*
  106.    * we now use ``colourtrns'' dithering algorithm, where X is the
  107.    * destination colour, and all values are (r, g, b) tuples
  108.    * topleft <-- X
  109.    * bottomright <-- X - (topleft - X)
  110.    * topright <-- X - (((topleft - X) + (bottomright - X)) / 2)
  111.    * bottomleft <-- X - (((topleft - X) + (bottomright - X) + (topright - X)) / 3)
  112.    *
  113.    * personally, I don't see why the need for divisions, as surely we are using:
  114.    *    "OK we missed X by N, therefore compensate by choosing X - N"
  115.    *
  116.    * humph, it works, anyway
  117.    */
  118.  
  119.   target_red = (colour >> (1 * 8)) & 0xff; target_red |= target_red << 8;
  120.   target_grn = (colour >> (2 * 8)) & 0xff; target_grn |= target_grn << 8;
  121.   target_blu = (colour >> (3 * 8)) & 0xff; target_blu |= target_blu << 8;
  122.   dither[0][0] = (*fn)(&err, target_red, target_grn, target_blu);
  123.   err_red = err.colour.red; err_grn = err.colour.grn; err_blu = err.colour.blu;
  124.   /*
  125.    * the err.colour is the error in representing the input red, grn, blu
  126.    * on later iterations we need to add in the error of the output colour from the target colour
  127.    */
  128.  
  129.   red = target_red + err_red;
  130.   grn = target_grn + err_grn;
  131.   blu = target_blu + err_blu;
  132.   t = dither[1][1] = (*fn)(&err, red, grn, blu);
  133.   red = err.colour.red; grn = err.colour.grn; blu = err.colour.blu;
  134.   err_red += red; err_grn += grn; err_blu += blu;               /* local error */
  135.   red = (t << (16 - (1*5))) & 0xf800; red |= red >> 10; red |= red >> 5; err_red += target_red - red;
  136.   grn = (t << (16 - (2*5))) & 0xf800; grn |= grn >> 10; grn |= grn >> 5; err_grn += target_grn - grn;
  137.   blu = (t << (16 - (3*5))) & 0xf800; blu |= blu >> 10; blu |= blu >> 5; err_blu += target_blu - blu;
  138.  
  139.   red = target_red + (err_red / 2);
  140.   grn = target_grn + (err_grn / 2);
  141.   blu = target_blu + (err_blu / 2);
  142.   t = dither[0][1] = (*fn)(&err, red, grn, blu);
  143.   red = err.colour.red; grn = err.colour.grn; blu = err.colour.blu;
  144.   err_red += red; err_grn += grn; err_blu += blu;               /* local error */
  145.   red = (t << (16 - (1*5))) & 0xf800; red |= red >> 10; red |= red >> 5; err_red += target_red - red;
  146.   grn = (t << (16 - (2*5))) & 0xf800; grn |= grn >> 10; grn |= grn >> 5; err_grn += target_grn - grn;
  147.   blu = (t << (16 - (3*5))) & 0xf800; blu |= blu >> 10; blu |= blu >> 5; err_blu += target_blu - blu;
  148.  
  149.   red = target_red + (err_red / 3);
  150.   grn = target_grn + (err_grn / 3);
  151.   blu = target_blu + (err_blu / 3);
  152.   dither[1][0] = (*fn)(&err, red, grn, blu);
  153. }
  154.  
  155.  
  156.